package sz.com.postoffice.jxyzwgcase.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import sz.com.postoffice.jxyzwgcase.core.ADOReturnBody;
import sz.com.postoffice.jxyzwgcase.dao.master.*;
import sz.com.postoffice.jxyzwgcase.dao.node.IOneClickResponseDao;
import sz.com.postoffice.jxyzwgcase.dao.node.TOperationtargetDao;
import sz.com.postoffice.jxyzwgcase.dao.node.TOperationtargetInfoDao;
import sz.com.postoffice.jxyzwgcase.pojo.*;
import sz.com.postoffice.jxyzwgcase.service.ConstantDbService;
import sz.com.postoffice.jxyzwgcase.service.OperationTargetService;
import sz.com.postoffice.jxyzwgcase.service.UserService;
import sz.com.postoffice.jxyzwgcase.utils.DateStrUtil;
import sz.com.postoffice.jxyzwgcase.utils.ExcelUtils;
import sz.com.postoffice.jxyzwgcase.utils.HttpsUtil;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述:
 *
 * @author baiyu, du
 * @date 2020/12/15 9:25
 */
@Service
@Slf4j
public class OperationTargetServiceImpl implements OperationTargetService {

    @Resource
    private UserAdoDao userAdoDao;
    @Resource
    private CustomerDao customerDao;
    @Resource
    private InterviewFeedbackDao interviewFeedbackDao;
    @Resource
    private ConstantDbService constantDbService;
    @Resource
    private OneClickResponseService oneClickResponseService;
    @Resource
    private EnterpriseCustomerContractDao enterpriseCustomerContractDao;
    @Resource
    private UserService userService;
    @Resource
    private TOperationtargetDao tOperationtargetDao;
    @Resource
    private TOperationtargetInfoDao infoDao;

    @Resource
    private TGridDao tGridDao;
    @Value("${ADO.User_behavior_URl}")
    private String url;
    @Value("${ADO.User_behavior_scopeId}")
    private String scopeId;

    @Override
    public List<OperationTargetReturn> getOperationTargetByCity(StatParam statParam) {
        List<OperationTargetReturn> resultList = new ArrayList<>();
        List<String> deptCodes = statParam.getDeptCodes();
        //  查询所有部门的运营数据
        Map<String, OperationTargetReturn> operationTargets = findOperationTargetByStatParam(statParam);
        //  查询当前环境所有的部门信息
        Map<String, Map<String, String>> allDeptCodeMap = new HashMap<>();
        for (Map<String, String> stringMap : tGridDao.findAllDept()) {
            allDeptCodeMap.put(stringMap.get("dept_code"), stringMap);
        }
        //根据查询部门添加返回行数据，每个部门都需要占用一行,未查询到数据直接new对象
        for (String queryDeptCode : deptCodes) {
            //从map中获取运营数据信息
            OperationTargetReturn operationTargetReturn = operationTargets.get(queryDeptCode);
            if (operationTargetReturn == null) {
                OperationTargetReturn row = new OperationTargetReturn();
                row.setErrorMassage("统计周期不存在此营业部");
                row.setDeptCode(queryDeptCode);
                Map<String, String> deptDetail = allDeptCodeMap.get(queryDeptCode);
                if (deptDetail != null) {
                    row.setCityCode(deptDetail.get("city_code"));
                    row.setCityName(deptDetail.get("city_name"));
                    row.setDeptName(deptDetail.get("dept_name"));
                } else {
                    row.setCityCode("-");
                    row.setCityName("-");
                    row.setDeptName("-");
                }

                resultList.add(row);
                continue;
            }
            resultList.add(operationTargetReturn);
        }
        //市统计查询
        Set<String> cities = resultList.stream().collect(Collectors.groupingBy(OperationTargetReturn::getCityCode)).keySet();
        String type = queryType(statParam);
        List<OperationTargetReturn> citiesList = tOperationtargetDao.findCityTotal(statParam.getEndDate(), type, cities);
        resultList.addAll(citiesList);

        //排序集合:按照城市名称
        resultList.sort(new Comparator<OperationTargetReturn>() {
            @Override
            public int compare(OperationTargetReturn o1, OperationTargetReturn o2) {
                int i = o1.getCityCode().compareTo(o2.getCityCode());
                if (i != 0) return i;
                if ("市统计".equals(o1.getDeptName())) return 1;
                if ("市统计".equals(o2.getDeptName())) return -1;
                return 0;
            }
        });
        return resultList;
    }

    @Override
    public XSSFWorkbook getOperationTargetExportExcel(StatParam statParam, String type)  {

        List<OperationTargetReturn> list = getOperationTargetByCity(statParam);
        if (list.isEmpty()) {
            log.info("sz.com.postoffice.jxyzwgcase.service.impl.OperationTargetServiceImpl.getOperationTargetExportExcel: No export data");
            return null;
        }
        //获取模板文件
        String templatePath = null;
        int beginRow = 3;//写入起始行，当前行，下一行 记录
        int mergedBeginRow = 3;//合并单元格起始行

        if ("cities2".equals(type)) {
            templatePath = "templates" + File.separator + "OperationDepartment.xlsx";
        } else if ("usageDetails".equals(type)) {
            templatePath = "templates" + File.separator + "usageDetails.xlsx";
            beginRow = 2;
            mergedBeginRow = 2;
        } else {
            log.error("sz.com.postoffice.jxyzwgcase.service.impl.OperationTargetServiceImpl.getOperationTargetExportExcel: Unknown export type");
            return null;
        }

        ClassPathResource classPathResource = new ClassPathResource(templatePath);
        InputStream inputStream = null;
        try {
            inputStream = classPathResource.getInputStream();
        } catch (IOException e) {
            log.error("Failed to get template file",e);
            return null;
        }

        XSSFWorkbook excel = null;
        try {
            excel = new XSSFWorkbook(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        //获取sheet表格
        XSSFSheet sheet = excel.getSheetAt(0);

        int writeRow = beginRow;
        for (OperationTargetReturn operationTargetReturn : list) {
            Map<Integer, String> rowMap = null;
            if ("cities2".equals(type)) {
                rowMap = convertWriteValue(operationTargetReturn);
            } else {
                rowMap = convertWriteValue4UsageDetails(operationTargetReturn);
            }
            for (Map.Entry<Integer, String> entry : rowMap.entrySet()) {
                ExcelUtils.writeCellValue(sheet, writeRow, entry.getKey(), entry.getValue());
            }
            String cityCode = operationTargetReturn.getCityCode();//获取当前行城市code
            //换下一行，等待下次写入数据
            writeRow++;
            //合并单元格，（分公司，第一列）
            try {
                String lastCityCode = list.get(writeRow - beginRow).getCityCode();//获取下一行城市code
                if (!cityCode.equals(lastCityCode)) {
                    //合并行操作
                    if (mergedBeginRow != writeRow - 1) {
                        ExcelUtils.mergedCell(sheet, mergedBeginRow, writeRow - 1, 0, 0);
                    }
                    mergedBeginRow = writeRow;
                }
            } catch (IndexOutOfBoundsException e) {
                //合并最后一个城市行操作，list中已经没有数据了
                ExcelUtils.mergedCell(sheet, mergedBeginRow, writeRow - 1, 0, 0);
            }
        }

        return excel;
    }

    /**
     * app使用情况，单元格和excel表格对应关系
     *
     * @param operationTargetReturn
     * @return
     */
    private Map<Integer, String> convertWriteValue4UsageDetails(OperationTargetReturn operationTargetReturn) {
        Map<Integer, String> map = new HashMap<>();
        map.put(0, operationTargetReturn.getCityName());
        map.put(1, operationTargetReturn.getDeptName());
        map.put(2, operationTargetReturn.getAppUserNum().toString());
        map.put(3, operationTargetReturn.getNoticeCount().toString());
        map.put(4, operationTargetReturn.getSignInCount().toString());
        map.put(5, operationTargetReturn.getDailyTaskCount().toString());
        map.put(6, operationTargetReturn.getEnterpriseRecordCount().toString());
        map.put(7, operationTargetReturn.getVisitCount().toString());
        map.put(8, operationTargetReturn.getWorkDailyCount().toString());
        map.put(9, operationTargetReturn.getSalaryForecastCount().toString());
        map.put(10, operationTargetReturn.getOneDelivery().toString());
        map.put(11, operationTargetReturn.getOneEmailQuery().toString());
        map.put(12, operationTargetReturn.getOneCollect().toString());
        return map;
    }

    @Override
    public List<OperationtargetInfo> usageDetails(StatParam statParam) {
        OperationtargetInfo queryInfo = new OperationtargetInfo();
        queryInfo.setFunctionName(statParam.getFunctionName());

        //如果传入参数有部门的code那么按照部门查询
        List<String> deptCodes = statParam.getDeptCodes();
        if (CollectionUtils.isNotEmpty(deptCodes) && deptCodes.size() == 1) {
            queryInfo.setDeptCode(deptCodes.get(0));
            return infoDao.selectPeriodByEntity(statParam.getStartDate(), statParam.getEndDate(), queryInfo);
        }
        //没有传部门code或者部门code不是一个看城市code是否为一个进行查询
        List<String> cityCodes = statParam.getCityCodes();
        if (CollectionUtils.isNotEmpty(cityCodes) && cityCodes.size() == 1) {
            queryInfo.setCityCode(cityCodes.get(0));
            return infoDao.selectPeriodByEntity(statParam.getStartDate(), statParam.getEndDate(), queryInfo);
        }

        return null;
    }


    /**
     * 根据StatParam从数据库查询数据，返回当前时间段的所有查询部门的结果,将部门的名称作为key（实际库中存的是部门的code）
     *
     * @param statParam
     * @return
     */
    private Map<String, OperationTargetReturn> findOperationTargetByStatParam(StatParam statParam) {
        String type = queryType(statParam);
        Map<String, OperationTargetReturn> allOperationTargetMap = new HashMap<>();
        for (OperationTargetReturn operationTarget : tOperationtargetDao.findByDeptCodes(statParam.getEndDate(), type, statParam.getDeptCodes())) {
            allOperationTargetMap.put(operationTarget.getDeptCode(), operationTarget);
        }
        return allOperationTargetMap;
    }

    /**
     * 查询类型判断，日 周 月
     *
     * @param statParam
     * @return
     */
    private String queryType(StatParam statParam) {
        String type = null;
        String startDate = statParam.getStartDate();
        String endDate = statParam.getEndDate();
        int days = DateStrUtil.getDays(startDate, endDate).size();
        if (days == 1) {
            type = "day";
        } else if (days == 7) {
            type = "week";
        } else {
            type = "month";
        }
        return type;
    }

    /**
     * 根据城市code从list中取出 completedRate
     *
     * @param list
     * @param cityCode
     * @return
     */
    private String completedRateBycity(List<Map> list, String cityCode) {
        if (cityCode == null || list == null) {
            return "--";
        }
        for (Map map : list) {
            if (cityCode.equals(map.get("city_code").toString())) {
                return map.get("completedRate").toString();
            }
        }
        return "--";
    }

    /**
     * 查询市级24小时响应率
     *
     * @param startTime
     * @param endTime
     * @param processDefineName
     * @return
     */
    private List<Map> calculateClose24forCity(String startTime, String endTime, String processDefineName) {
        HashMap<String, String> map = new HashMap<>();
        map.put("startTime", startTime);
        map.put("endTime", endTime);
        map.put("processDefineName", processDefineName);
        return oneClickResponseService.collectionMarketingForCity(map);
    }


    /**
     * 绑定列号和对应值
     *
     * @param operationTargetReturn
     * @return
     */
    private Map<Integer, String> convertWriteValue(OperationTargetReturn operationTargetReturn) {
        Map<Integer, String> map = new HashMap<>();
        map.put(0, operationTargetReturn.getCityName());
        map.put(1, operationTargetReturn.getDeptName());
        //签到打卡
        map.put(2, operationTargetReturn.getSignInCount().toString());
        map.put(3, operationTargetReturn.getSignInPercent());
        //企业建档
        map.put(4, operationTargetReturn.getEnterpriseRecordCount().toString());
        map.put(5, operationTargetReturn.getEnterpriseRecordPercent());
        //资源走访
        map.put(6, operationTargetReturn.getVisitCount().toString());
        map.put(7, operationTargetReturn.getVisitPercent());

        //活跃用户统计
        map.put(8, operationTargetReturn.getActiveUserCount().toString());
        map.put(9, operationTargetReturn.getActiveUserPercent());
        //薪资测算
        map.put(10, operationTargetReturn.getSalaryForecastCount().toString());
        map.put(11, operationTargetReturn.getSalaryForecastPercent());
        //一键需求响应
        map.put(12, operationTargetReturn.getOneDeliveryCount().toString());
        map.put(13, operationTargetReturn.getOneDeliveryPercent());
        map.put(14, operationTargetReturn.getOneEmailQueryCount().toString());
        map.put(15, operationTargetReturn.getOneEmailQueryPercent());
        map.put(16, operationTargetReturn.getOneCollectCount().toString());
        map.put(17, operationTargetReturn.getOneCollectPercent());

//        map.put(18,operationTarget.());
        //走访客户数
        map.put(19, operationTargetReturn.getVisitCustomerCount().toString());
        //增建档客户数
        map.put(20, operationTargetReturn.getIncreaseCustomerCount().toString());
        //及时关闭率
        map.put(21, operationTargetReturn.getOneDeliveryPercentClose24());
        map.put(22, operationTargetReturn.getOneEmailQueryPercentClose24());
        map.put(23, operationTargetReturn.getOneCollectPercentClose24());
        //签约客户数
        map.put(24, operationTargetReturn.getSignCustomerCount().toString());

        map.put(25, operationTargetReturn.getErrorMassage());
        return map;
    }

    /**
     * 24小时响应率
     */
    private void calculateClose24(String startTime, String endTime, String city_code, String dept_code, OperationTargetReturn operationTargetReturn) {
        HashMap<String, String> map = new HashMap<>();
        map.put("empDeptCode", dept_code);
        map.put("cityCode", city_code);
        map.put("startTime", startTime);
        map.put("endTime", endTime);
        String completedRate = "";

        map.put("processDefineName", "投递质量");
        List<Map> mapsDelivery = oneClickResponseService.collectionMarketingForDepartment(map);
        if (mapsDelivery.size() > 0) {
            completedRate = mapsDelivery.get(0).get("completedRate").toString();
            operationTargetReturn.setOneDeliveryPercentClose24(completedRate);
            operationTargetReturn.setOneDeliveryCount(Integer.parseInt(mapsDelivery.get(0).get("total").toString()));
        } else {
            operationTargetReturn.setOneDeliveryPercentClose24("--");
            operationTargetReturn.setOneDeliveryCount(0);
        }

        map.put("startTime", startTime);
        map.put("endTime", endTime);
        map.put("processDefineName", "邮件直查");
        List<Map> mapsEmail = oneClickResponseService.collectionMarketingForDepartment(map);
        if (mapsEmail.size() > 0) {
            completedRate = mapsEmail.get(0).get("completedRate").toString();
            operationTargetReturn.setOneEmailQueryPercentClose24(completedRate);
            operationTargetReturn.setOneEmailQueryCount(Integer.parseInt(mapsEmail.get(0).get("total").toString()));
        } else {
            operationTargetReturn.setOneEmailQueryPercentClose24("--");
            operationTargetReturn.setOneEmailQueryCount(0);
        }

        map.put("startTime", startTime);
        map.put("endTime", endTime);
        map.put("processDefineName", "揽收营销");
        List<Map> mapsClick = oneClickResponseService.collectionMarketingForDepartment(map);
        if (mapsClick.size() > 0) {
            completedRate = mapsClick.get(0).get("completedRate").toString();
            operationTargetReturn.setOneCollectPercentClose24(completedRate);
            operationTargetReturn.setOneCollectCount(Integer.parseInt(mapsClick.get(0).get("total").toString()));
        } else {
            operationTargetReturn.setOneCollectPercentClose24("--");
            operationTargetReturn.setOneCollectCount(0);
        }
    }

    /**
     * 走访客户数，新增建档客户数
     *
     * @param startTime
     * @param endTime
     * @param operationTargetReturn
     * @param adoIdList
     */
    private void calculateCoustomer(String startTime, String endTime, OperationTargetReturn operationTargetReturn, ArrayList<String> adoIdList) {
        operationTargetReturn.setVisitCustomerCount(interviewFeedbackDao.findMumberByAdoIdList(adoIdList, startTime, endTime));
        operationTargetReturn.setIncreaseCustomerCount(customerDao.findIncreaseCustomerCountByAdoIdList(adoIdList, startTime, endTime));
    }

    /**
     * 百分数计算
     *
     * @param num1
     * @param num2
     * @return
     */
    private String percent(int num1, int num2) {
        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后2位
        numberFormat.setMaximumFractionDigits(2);
        return numberFormat.format((float) num1 / (float) num2 * 100) + "%";
    }


    @Override
    public void collectDataFromADO(String[] dates) {
        ArrayList<OperationTargetReturn> insertList = new ArrayList<>();
        ArrayList<OperationtargetInfo> insertInfo = new ArrayList<>();
        ArrayList<OperationtargetInfo> insertInfoTemp = new ArrayList<>();
        String startTime = dates[0] + " 00:00:00";
        String endTime = dates[dates.length - 1] + " 23:59:59";
        //统计周期类型，日，周，月
        String collectType = null;
        boolean collectTypeDay = false;
        if (dates.length == 1) {
            collectType = "day";
            collectTypeDay = true;
        } else if (dates.length == 7) {
            collectType = "week";
        } else {
            collectType = "month";
        }
        //获取数据，ado接口数据，所有部门，functionCode配置常量信息
        HashSet<String> activeUserSet = new HashSet<>();
        Map<String, List<BodyResult>> bodyResults = callADOInterface(dates, activeUserSet);
        List<Map<String, String>> deptCodes = tGridDao.findAllDept();
        Map<String, String> functionCodeMap = constantDbService.findByModel("TOperationtarget");
        //按照城市排序集合，已方便做市统计。cityRemake表示是否新建市统计行对象，totalUser4City表示市内中人数
        deptCodes.sort(Comparator.comparing(o -> o.get("city_code")));
        boolean cityRemake = true;
        OperationTargetReturn dbRow4city = null;
        int totalUser4City = 0;
        List<Map> oneDelivery4cityList = calculateClose24forCity(startTime, endTime, "投递质量");
        List<Map> oneEmailQuery4cityList = calculateClose24forCity(startTime, endTime, "邮件直查");
        List<Map> oneCollect4cityList = calculateClose24forCity(startTime, endTime, "揽收营销");
        //分部门统计数据
        for (int i = 0; i < deptCodes.size(); i++) {
            Map<String, String> dept = deptCodes.get(i);
            String deptCode = dept.get("dept_code");
            String deptName = dept.get("dept_name");
            String cityCode = dept.get("city_code");
            String cityName = dept.get("city_name");
            //查询部门里面所有人，不包含AdoID为空的
            Map<String, UserAdo> allUserMap = getAllUserByDept(deptCode);
            ArrayList<String> allUser = new ArrayList<>(allUserMap.keySet());
            //新建市统计行
            if (cityRemake) {
                dbRow4city = new OperationTargetReturn();
                dbRow4city.setCityCode(cityCode);
                dbRow4city.setCityName(cityName);
                dbRow4city.setDeptName("市统计");
                dbRow4city.setDeptCode("市统计");
                dbRow4city.setDate(dates[dates.length - 1]);
                dbRow4city.setType(collectType);
                cityRemake = false;
                totalUser4City = 0;
            }
            //判断部门是否存在用户
            if (CollectionUtils.isNotEmpty(allUser)) {
                //新建营业部统计行  ，数据库中用id表示城市和营业部名称
                OperationTargetReturn dbRow = new OperationTargetReturn();
                dbRow.setCityCode(cityCode);
                dbRow.setCityName(cityName);
                dbRow.setDeptCode(deptCode);
                dbRow.setDeptName(deptName);
                dbRow.setDate(dates[dates.length - 1]);
                dbRow.setType(collectType);

                //遍历部门中的每个人,累计部门中8个模块使用人数,app使用人数统计，活跃用户数统计
                for (String adoid : allUser) {
                    List<BodyResult> values = bodyResults.get(adoid);
                    String userName = allUserMap.get(adoid).getUserName();
                    if (values == null) continue;
                    for (BodyResult value : values) {
                        String functionCode = value.getFunctionCode();
                        String functionName = value.getFunctionName();
                        if (functionCodeMap.get("signin").equals(functionCode) || functionCodeMap.get("clockin").equals(functionCode) || functionCodeMap.get("clock-in").equals(functionCode)) {
                        	if (!checkOperationtargetInfo(insertInfoTemp,adoid)) {
                        		dbRow.setSignInCount(dbRow.getSignInCount() + 1);
                        		insertInfoTemp.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "signin", adoid, userName));
                                if (collectTypeDay) {
                                    insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "signin", adoid, userName));
                                    continue;
                                }
                        	}
                        }
                        if (functionCodeMap.get("enterpriserecord").equals(functionCode)) {
                            dbRow.setEnterpriseRecordCount(dbRow.getEnterpriseRecordCount() + 1);
                            if (collectTypeDay) {
                                insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "enterpriserecord", adoid, userName));
                                continue;
                            }
                        }
                        if (functionCodeMap.get("visit").equals(functionCode)) {
                            dbRow.setVisitCount(dbRow.getVisitCount() + 1);
                            if (collectTypeDay) {
                                insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "visit", adoid, userName));
                                continue;
                            }
                        }
                        if (functionCodeMap.get("salaryforecas").equals(functionCode)) {
                            dbRow.setSalaryForecastCount(dbRow.getSalaryForecastCount() + 1);
                            if (collectTypeDay) {
                                insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "salaryforecas", adoid, userName));
                                continue;
                            }
                        }

                        if (functionCodeMap.get("onedelivery").equals(functionCode)) {
                            dbRow.setOneDelivery(dbRow.getOneDelivery() + 1);
                            if (collectTypeDay) {
                                insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "onedelivery", adoid, userName));
                                continue;
                            }
                        }
                        if (functionCodeMap.get("oneemailquery").equals(functionCode)) {
                            dbRow.setOneEmailQuery(dbRow.getOneEmailQuery() + 1);
                            if (collectTypeDay) {
                                insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "oneemailquery", adoid, userName));
                                continue;
                            }
                        }
                        if (functionCodeMap.get("onecollect").equals(functionCode)) {
                            dbRow.setOneCollect(dbRow.getOneCollect() + 1);
                            if (collectTypeDay) {
                                insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "onecollect", adoid, userName));
                                continue;
                            }
                        }
                        if (functionCodeMap.get("notice").equals(functionCode)) {
                            dbRow.setNoticeCount(dbRow.getNoticeCount() + 1);
                            if (collectTypeDay) {
                                insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "notice", adoid, userName));
                                continue;
                            }
                        }
                        if (functionCodeMap.get("workDaily").equals(functionCode)) {
                            dbRow.setWorkDailyCount(dbRow.getWorkDailyCount() + 1);
                            if (collectTypeDay) {
                                insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "workDaily", adoid, userName));
                                continue;
                            }
                        }
                        if (functionCodeMap.get("dailyTask").equals(functionCode)) {
                            dbRow.setDailyTaskCount(dbRow.getDailyTaskCount() + 1);
                            if (collectTypeDay) {
                                insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, "dailyTask", adoid, userName));
                                continue;
                            }
                        }

                        if (collectTypeDay) {
                            insertInfo.add(new OperationtargetInfo(dates[dates.length - 1], cityCode, cityName, deptCode, deptName, functionCode, functionName, adoid, userName));
                        }
                    }
                    //活跃用户数统计
                    if (activeUserSet.contains(adoid)) {
                        dbRow.setActiveUserCount(dbRow.getActiveUserCount() + 1);
                    }
                    //app使用人数统计
                    dbRow.setAppUserNum(dbRow.getAppUserNum() + 1);
                }
                //8个模块使用率
                rateOfUtilization(allUser.size(), dbRow);
                //走访与建档客户数查询
                calculateCoustomer(startTime, endTime, dbRow, allUser);
                //当前周期内新增签约客户数查询
                dbRow.setSignCustomerCount(enterpriseCustomerContractDao.findMumberByAdoIdList(allUser, startTime, endTime));
                //一键需求响应统提单数、及时关闭率 接口调用（营业部级别）
                calculateClose24(startTime, endTime, cityCode, deptCode, dbRow);
                insertList.add(dbRow);
                //市总累计:把内个营业部的使用人数加起来,提单数和；以及内个部门总人数
                cityTotal(dbRow4city, dbRow);
                totalUser4City += allUser.size();
            }
            //市统计,集合排序后当出现city_Code不一致为下一个市,如果是末尾也做市统计
            if (i == (deptCodes.size() - 1) || !cityCode.equals(deptCodes.get(i + 1).get("city_code"))) {
                if (totalUser4City > 0) {
                    //8个模块使用率
                    rateOfUtilization(totalUser4City, dbRow4city);
                    //24小时关闭率
                    dbRow4city.setOneDeliveryPercentClose24(completedRateBycity(oneDelivery4cityList, cityCode));
                    dbRow4city.setOneEmailQueryPercentClose24(completedRateBycity(oneEmailQuery4cityList, cityCode));
                    dbRow4city.setOneCollectPercentClose24(completedRateBycity(oneCollect4cityList, cityCode));
                    insertList.add(dbRow4city);
                }
                cityRemake = true;//新增市统计对象标记为true
            }

        }

        if (!insertInfo.isEmpty()) {
            infoDao.insertList(insertInfo);
        }
        System.out.println("insertInfo size:" + insertInfo.size());
        System.out.println("insertList size:" + insertList.size());
        tOperationtargetDao.insertList(insertList);
    }
    
    /**
     * 检查打卡数据是否重复计算
     * @param insertInfo
     * @param adoID
     * @return
     */
    private boolean checkOperationtargetInfo(ArrayList<OperationtargetInfo> insertInfo, String adoID) {
    	boolean status = false;
    	for (OperationtargetInfo info : insertInfo) {
    		if (info.getUserId().equals(adoID) && "signin".equals(info.getFunctionName())) {
    			status = true;
    		}
    	}
    	return status;
    }
    /**
     * 市累计人数
     *
     * @param dbRow4city
     * @param dbRow
     */
    private void cityTotal(OperationTargetReturn dbRow4city, OperationTargetReturn dbRow) {
        dbRow4city.setSignInCount(dbRow.getSignInCount() + dbRow4city.getSignInCount());
        dbRow4city.setEnterpriseRecordCount(dbRow.getEnterpriseRecordCount() + dbRow4city.getEnterpriseRecordCount());
        dbRow4city.setVisitCount(dbRow.getVisitCount() + dbRow4city.getVisitCount());
        dbRow4city.setSalaryForecastCount(dbRow.getSalaryForecastCount() + dbRow4city.getSalaryForecastCount());
        dbRow4city.setOneDeliveryCount(dbRow.getOneDeliveryCount() + dbRow4city.getOneDeliveryCount());
        dbRow4city.setOneEmailQueryCount(dbRow.getOneEmailQueryCount() + dbRow4city.getOneEmailQueryCount());
        dbRow4city.setOneCollectCount(dbRow.getOneCollectCount() + dbRow4city.getOneCollectCount());
        dbRow4city.setActiveUserCount(dbRow.getActiveUserCount() + dbRow4city.getActiveUserCount());
        dbRow4city.setVisitCustomerCount(dbRow.getVisitCustomerCount() + dbRow4city.getVisitCustomerCount());
        dbRow4city.setIncreaseCustomerCount(dbRow.getIncreaseCustomerCount() + dbRow4city.getIncreaseCustomerCount());
        dbRow4city.setSignCustomerCount(dbRow.getSignCustomerCount() + dbRow4city.getSignCustomerCount());
        dbRow4city.setOneDelivery(dbRow.getOneDelivery() + dbRow4city.getOneDelivery());
        dbRow4city.setOneCollect(dbRow.getOneCollect() + dbRow4city.getOneCollect());
        dbRow4city.setOneEmailQuery(dbRow.getOneEmailQuery() + dbRow4city.getOneEmailQuery());
        dbRow4city.setNoticeCount(dbRow.getNoticeCount() + dbRow4city.getNoticeCount());
        dbRow4city.setWorkDailyCount(dbRow.getWorkDailyCount() + dbRow4city.getWorkDailyCount());
        dbRow4city.setDailyTaskCount(dbRow.getDailyTaskCount() + dbRow4city.getDailyTaskCount());
        dbRow4city.setAppUserNum(dbRow.getAppUserNum() + dbRow4city.getAppUserNum());
    }


    private void rateOfUtilization(int totalPeople, OperationTargetReturn row) {
        row.setSignInPercent(percent(row.getSignInCount(), totalPeople));
        row.setEnterpriseRecordPercent(percent(row.getEnterpriseRecordCount(), totalPeople));
        row.setVisitPercent(percent(row.getVisitCount(), totalPeople));
        row.setSalaryForecastPercent(percent(row.getSalaryForecastCount(), totalPeople));
        row.setOneDeliveryPercent(percent(row.getOneDelivery(), totalPeople));
        row.setOneEmailQueryPercent(percent(row.getOneEmailQuery(), totalPeople));
        row.setOneCollectPercent(percent(row.getOneCollect(), totalPeople));
        row.setActiveUserPercent(percent(row.getActiveUserCount(), totalPeople));
    }

    /**
     * 根据部门id查询部门里面所用在职人员，并排除空的用户
     *
     * @param deptCode
     * @return
     */
    private Map<String, UserAdo> getAllUserByDept(String deptCode) {
        //查询部门里面所有人
        UserAdo userAdoTemp = new UserAdo();
        userAdoTemp.setDeptCode(deptCode);
        userAdoTemp.setEmpStatus("01");
        List<UserAdo> allUser = userAdoDao.findByListEntity(userAdoTemp);
        // daoID查空
        Map<String, UserAdo> adoMap = new HashMap<>();
        for (UserAdo userAdo : allUser) {
            if (StringUtils.isNotBlank(userAdo.getAdoId())) {
                adoMap.put(userAdo.getAdoId(), userAdo);
            }
        }
        return adoMap;
    }

    /**
     * 请求华为接口方法
     * 由于想返回两个参数，一个用返回值{用户id，使用模块functionCode}，一个用入参传递地址值{活跃用户id}
     */
    private Map<String, List<BodyResult>> callADOInterface(String[] dates, Set<String> activeUser) {
        String adoToken = userService.getADOToken(new JSONObject());
        Set<BodyResult> adoResultBody = new HashSet<>();
        Map<String, Set<String>> loginUser = new HashMap<>();
        for (String date : dates) {
            HashMap<String, String> token = new HashMap<>();
            token.put("gc-authentication", adoToken);
            body body = new body(date, scopeId);
            String returnDate = HttpsUtil.postAddHeader(url, JSON.toJSONString(body), token);
            ADOReturnBody returnBody = JSONObject.parseObject(returnDate, ADOReturnBody.class);
            if (returnBody.getCode() == 1) {
                List<Map<String, String>> result = returnBody.getResult();
                for (Map<String, String> map : result) {
                    String userId = map.get("userId");
                    String functionCode = map.get("functionCode");
                    String functionName = map.get("functionName");
                    if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(functionCode)) {
                        adoResultBody.add(new BodyResult(functionCode, functionName, userId));
                        if (functionCode != null && functionCode.contains("login")) {
                            Set<String> set = loginUser.get(userId);
                            if (set == null) {
                                HashSet<String> hashSet = new HashSet<>();
                                hashSet.add(date);
                                loginUser.put(userId, hashSet);
                            } else {
                                set.add(date);
                            }
                        }
                    }
                }
            }
        }
        // 统计周期内登录天数超过半数以上用户,算活跃
        int benchmark = dates.length / 2 + 1;
        for (String userId : loginUser.keySet()) {
            if (loginUser.get(userId).size() >= benchmark) {
                activeUser.add(userId);
            }
        }
        return adoResultBody.stream().collect(Collectors.groupingBy(BodyResult::getUserId));
    }

    @Data
    private class body {
        private String date;
        private String scopeId;
        private String functionCode;

        public body(String date, String scopeId) {
            this.date = date;
            this.scopeId = scopeId;
        }
    }

    @Data
    private class BodyResult {
        private String functionCode;
        private String functionName;
        private String userId;

        public BodyResult(String functionCode, String functionName, String userId) {
            this.functionCode = functionCode;
            this.functionName = functionName;
            this.userId = userId;
        }


        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            BodyResult that = (BodyResult) o;
            return Objects.equals(functionCode, that.functionCode) &&
                    Objects.equals(userId, that.userId);
        }

        @Override
        public int hashCode() {
            return Objects.hash(functionCode, userId);
        }
    }
}
